#ifndef __PANEL_DISTORTION_H__
#define __PANEL_DISTORTION_H__

#include <wx/wx.h>
#include <wx/aui/aui.h>
#include <wx/wrapsizer.h>
#include <wx/event.h>
#include <wx/xml/xml.h>
#include "MyCommon.h"
#include "ctrl_equalizer.h"

#define DISTORTION_EQ_MAX 4

class MyEventDistortion : public wxCommandEvent {
public:
    MyEventDistortion(wxEventType eventType = wxEVT_NULL,int id = 0)
        : wxCommandEvent(eventType, id) {
            preset_index = 0;
        }

    // 克隆事件对象
//    [[nodiscard]] // C++17 才支持，意思就是函数返回值不能被忽略，否则编译器发出警告
    virtual wxEvent *Clone() const override {
        return new MyEventDistortion(*this);
    }

    void SetTone(double tone) {
        m_tone = tone;
    }
    void SetPostGain(double gain_output) {
        m_level = gain_output;
    }
    void SetDrive(double rate) {
        m_rate = rate;
    }
    void SetPreGain(double gain_input) {
        m_gain = gain_input;
    }
    void SetEnable(bool enable) {
        this->enable = enable;
    }
    void SetPresetIndex(const unsigned int index) {
        preset_index = index;
    }
    void SetWidth(double bandwidth) {
        m_bandwidth = bandwidth;
    }
    void SetFreq(double freq) {
        m_freq = freq;
    }

    double GetTone() {
        return m_tone;
    }
    double GetLevel() {
        return m_level;
    }
    double GetDrive() {
        return m_rate;
    }
    double GetGain() {
        return m_gain;
    }
    bool GetEnable() {
        return enable;
    }
    double GetWidth() {
        return m_bandwidth;
    }
    double GetFreq() {
        return m_freq;
    }
    int GetPresetIndex() {
        return preset_index;
    }

    void SetEqualizerParam(int band,FilterParam &param) {
        eq.frequency = param.frequency;
        eq.gain = param.gain;
        eq.qfactor = param.qfactor;
        eq.type = param.type;
        eq_band = band;
    }

    int GetEqualizerParam(FilterParam &param) {
        param = eq;
        return eq_band;
    }


private:
    FilterParam eq;
    int eq_band;
    double m_tone;
    double m_level;
    double m_rate;
    double m_gain;
    double m_freq;
    double m_bandwidth;
    bool enable;
    int preset_index;
};

wxDECLARE_EVENT(myEVT_DISTORTION, MyEventDistortion);
wxDECLARE_EVENT(myEVT_DISTORTION_TONE, MyEventDistortion);
wxDECLARE_EVENT(myEVT_DISTORTION_LEVEL, MyEventDistortion);
wxDECLARE_EVENT(myEVT_DISTORTION_DRIVE, MyEventDistortion);
wxDECLARE_EVENT(myEVT_DISTORTION_GAIN, MyEventDistortion);
wxDECLARE_EVENT(myEVT_DISTORTION_ENABLE, MyEventDistortion);
wxDECLARE_EVENT(myEVT_DISTORTION_FREQ, MyEventDistortion);
wxDECLARE_EVENT(myEVT_DISTORTION_WIDTH, MyEventDistortion);
wxDECLARE_EVENT(myEVT_DISTORTION_EQ, MyEventDistortion);


typedef void (wxEvtHandler::*MyDistortionEventFunction)(MyEventDistortion &);

#define MyDistortionEventHandler(func) \
    wxEVENT_HANDLER_CAST(MyDistortionEventFunction, func)

#define M_EVT_DISTORTION(id, fn) \
    wx__DECLARE_EVT1(myEVT_DISTORTION, id, MyDistortionEventHandler(fn))
#define M_EVT_DISTORTION_TONE(id, fn) \
    wx__DECLARE_EVT1(myEVT_DISTORTION_TONE, id, MyDistortionEventHandler(fn))
#define M_EVT_DISTORTION_LEVEL(id, fn) \
    wx__DECLARE_EVT1(myEVT_DISTORTION_LEVEL, id, MyDistortionEventHandler(fn))
#define M_EVT_DISTORTION_DRIVE(id, fn) \
    wx__DECLARE_EVT1(myEVT_DISTORTION_DRIVE, id, MyDistortionEventHandler(fn))
#define M_EVT_DISTORTION_GAIN(id, fn) \
    wx__DECLARE_EVT1(myEVT_DISTORTION_GAIN, id, MyDistortionEventHandler(fn))
#define M_EVT_DISTORTION_ENABLE(id, fn) \
    wx__DECLARE_EVT1(myEVT_DISTORTION_ENABLE, id, MyDistortionEventHandler(fn))
#define M_EVT_DISTORTION_FREQ(id, fn) \
    wx__DECLARE_EVT1(myEVT_DISTORTION_FREQ, id, MyDistortionEventHandler(fn))
#define M_EVT_DISTORTION_WIDTH(id, fn) \
    wx__DECLARE_EVT1(myEVT_DISTORTION_WIDTH, id, MyDistortionEventHandler(fn))
#define M_EVT_DISTORTION_EQ(id, fn) \
    wx__DECLARE_EVT1(myEVT_DISTORTION_EQ, id, MyDistortionEventHandler(fn))


class PanelDistortion : public wxPanel
{
public:
    PanelDistortion(const wxString &title, wxXmlNode *node, wxWindowID id = wxID_ANY, wxWindow *parent = nullptr);
    typedef struct
    {
        bool enable;
        float tone;
        float gain_output;
        float drive;
        float gain_input;
        float bandwidth;
        uint32_t freq;
        FilterParam eq[DISTORTION_EQ_MAX];
    }param_struct;
private:

    // enum{
    //     ID_TXT_TONE = ID_START_PANEL_DISTORTION,
    //     ID_TXT_LEVEL,
    //     ID_TXT_DRIVE,
    //     ID_TXT_GAIN,
    //     ID_TXT_FREQ,
    //     ID_TXT_WIDTH,
    //     ID_SLI_TONE,
    //     ID_SLI_LEVEL,
    //     ID_SLI_DRIVE,
    //     ID_SLI_GAIN,
    //     ID_SLI_FREQ,
    //     ID_SLI_WIDTH,
    //     ID_CHO_PRESET,
    //     ID_CHK_SWITCH,
    // };

    wxWindowID ID_TXT_TONE;
    wxWindowID ID_TXT_LEVEL;
    wxWindowID ID_TXT_DRIVE;
    wxWindowID ID_TXT_GAIN;
    wxWindowID ID_TXT_FREQ;
    wxWindowID ID_TXT_WIDTH;
    wxWindowID ID_SLI_TONE;
    wxWindowID ID_SLI_LEVEL;
    wxWindowID ID_SLI_DRIVE;
    wxWindowID ID_SLI_GAIN;
    wxWindowID ID_SLI_FREQ;
    wxWindowID ID_SLI_WIDTH;
    wxWindowID ID_CHO_PRESET;
    wxWindowID ID_CHK_SWITCH;
    wxWindowID ID_BTN_EQ;

    enum{
        EV_TONE=1,
        EV_POSTGAIN,
        EV_DRIVE,
        EV_PREGAIN,
        EV_ENABLE,
        EV_FREQ,
        EV_WIDTH,
    };


    wxAuiPaneInfo paneInfo;
    MyEventDistortion param_event;
    param_struct param;
    wxXmlNode *root_node;
    wxXmlNode *preset_node;
    int select_index;
    wxWindowID this_id;
    GraphicEqualizer *equalizer;
    //FilterType type,double frequency,double gain,double qfactor

public:
    const double tone_max = 1;
    const double tone_min = 0;
    const double tone_step = 0.01;
    const double outgain_max = 30;
    const double outgain_min = -30;
    const double outgain_step = 0.1;
    const double drive_max = 1;
    const double drive_min = 0;
    const double drive_step = 0.01;
    const double gain_max = 30;
    const double gain_min = 0;
    const double gain_step = 0.01;
    const double freq_max = 5000;
    const double freq_min = 50;
    const double freq_step = 1;
    const double bandwidth_max = 5;
    const double bandwidth_min = 0.5;
    const double bandwidth_step = 0.01;
    const char *attr_name_select = "select";
    const char *attr_name_preset_default = "default";
    const char *attr_name_param_tone = "tone";
    const char *attr_name_param_postgain = "postgain";
    const char *attr_name_param_drive = "drive";
    const char *attr_name_param_pregain = "pregain";
    const char *attr_name_param_enable = "enable";
    const char *attr_name_param_freq = "freq";
    const char *attr_name_param_bandwidth = "bandwidth";
    const char *attr_name_param_eq_type = "type";
    const char *attr_name_param_eq_freq = "freq";
    const char *attr_name_param_eq_gain = "gain";
    const char *attr_name_param_eq_q = "q";

    wxAuiPaneInfo &GetPaneInfo();
    void SetShow(bool show);
    double SetParamTone(double value);
    double SetParamPostGain(double value);
    double SetParamDrive(double value);
    double SetParamPreGain(double value);
    bool SetParamEnable(bool value);;
    double SetParamFreq(double value);
    double SetParamWidth(double value);
    double GetParamTone();
    double GetParamPostGain();
    double GetParamDrive();
    double GetParamPreGain();
    double GetParamFreq();
    double GetParamWidth();
    bool GetParamEnable();
    void SetPresetIndex(const unsigned int index);
    int GetPresetIndex();
    void PresetListClear(void);
    void AddPresetList(const wxString &preset_name);
    wxXmlNode *SaveCurrentParamsToNewPreset(wxXmlNode *root, const wxString &new_preset_name,int &is_same);
    bool WriteToXML(wxXmlNode *node);
    void SetParamEq(int band,FilterParam &eq);

private:
    void OnSliderChange(wxCommandEvent& event);
    void OnTextEnter(wxCommandEvent& event);
    void OnChkChange(wxCommandEvent& event);
    void OnCombChange(wxCommandEvent& event);
    void OnBtnEq(wxCommandEvent& event);
    void OnEqualizerEvent(MyEventEqualizer &event);
    void OnEqualizerFrequencyEvent(MyEventEqualizer &event);
    void OnEqualizerGainEvent(MyEventEqualizer &event);
    void OnEqualizerQFactorEvent(MyEventEqualizer &event);
    void OnEqualizerTypeEvent(MyEventEqualizer &event);


    void TrigerEvent(int ev);

    wxXmlNode *SelectPreset(const wxString name);


    // wxDECLARE_EVENT_TABLE();
};



#endif
